package com.hjxr.quota.define.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hjxr.common.utils.bean.BeanUtils;
import com.hjxr.quota.define.constant.DefineConstant;
import com.hjxr.quota.define.domain.*;
import com.hjxr.quota.define.dto.QuotaCreateDto;
import com.hjxr.quota.define.mapper.*;
import com.hjxr.quota.define.service.IQuotaFormulaService;
import com.hjxr.quota.util.SimpleFormulaAnalysis;
import com.hjxr.quota.define.domain.*;
import com.hjxr.quota.define.mapper.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 预指标公式存储表 服务实现类
 * </p>
 *
 * @author ma
 * @since 2020-10-20
 */
@Service
@Slf4j
public class QuotaFormulaServiceImpl extends ServiceImpl<QuotaFormulaMapper, QuotaFormula> implements IQuotaFormulaService {

    @Autowired
    private QuotaMapper quotaMapper;
    @Autowired
    private QuotaSourceMapper quotaSourceMapper;
    @Autowired
    private QuotaDimensionRelationMapper quotaDimensionRelationMapper;
    @Autowired
    private QuotaDimRelationDetailMapper quotaDimRelationDetailMapper;
    @Autowired
    private QuotaValueMapper quotaValueMapper;
    @Autowired
    private QuotaFormulaOperatorMapper quotaFormulaOperatorMapper;


    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean createQuotaByQuota(QuotaCreateDto quotaCreateDto) {
        String dimIds = "";
        Integer quotaId = null;
        List<Integer> quotaIds = new ArrayList<>();//存储计算公式中的预指标id集合
        List<Integer> dimIdList = new ArrayList<>();//存储共有具体维度id集合
        List<Object> formulaList = new ArrayList<>();//顺序存储计算公式各项内容（预指标id，计算符）
        Map<Integer, Float> quotaIdValueMap = new HashMap<>();//存储预指标id对应的共有维度的指标值

        try {
            Map<Integer, Integer> dimMap = quotaCreateDto.getDimIntMap();//具体维度id对应一级维度id 的map集合

            //插入指标表
            Quota quota = new Quota();
            quota.setStatus("1");
            BeanUtils.copyProperties(quotaCreateDto, quota);
            quota.setUpdateDate(new Date());
            quotaMapper.insert(quota);

            //插入指标公式表 挪到这 新增字段FORMULA_VALUE 存储每一个预指标值得sum值
            List<QuotaFormula> quotaFormulaList = quotaCreateDto.getQuotaFormulaList();
            int i = 1;
            for (QuotaFormula quotaFormula : quotaFormulaList) {
                quotaFormula.setQuotaId(quota.getId());
                quotaFormula.setOrderNum(i);
                save(quotaFormula);//执行插入
                if (quotaFormula.getFormulaType().equals("0")) {
                    quotaIds.add(quotaFormula.getFormulaTextId());//取计算公式中的预指标id集合
                }
                i++;
            }

            //插入指标来源表
            QuotaSource quotaSource = new QuotaSource();
            quotaSource.setQuotaId(quota.getId());
            quotaSource.setFormula(quotaCreateDto.getFormula());
            quotaSource.setUpdateDate(new Date());

            for (Map.Entry<Integer, Integer> entry : dimMap.entrySet()) {
                dimIds += entry.getKey() + ",";
                //插入指标与维度关系表（一级维度）
                QuotaDimensionRelation quotaDimensionRelation = new QuotaDimensionRelation();
                quotaDimensionRelation.setQuotaId(quota.getId());
                quotaDimensionRelation.setDimensionId(entry.getValue());
                quotaDimensionRelation.setUpdateDate(new Date());

                quotaDimensionRelationMapper.insert(quotaDimensionRelation);

                //插入指标与维度关系表（具体维度）
                QuotaDimRelationDetail quotaDimRelationDetail = new QuotaDimRelationDetail();
                quotaDimRelationDetail.setQuotaId(quota.getId());
                quotaDimRelationDetail.setDimensionId(entry.getKey());
                quotaDimRelationDetail.setRootDimId(entry.getValue());
                quotaDimRelationDetail.setUpdateDate(new Date());

                quotaDimRelationDetailMapper.insert(quotaDimRelationDetail);
                dimIdList.add(entry.getKey());
            }
            quotaSource.setDimensions(dimIds.substring(0, dimIds.length() - 1));
            quotaSourceMapper.insert(quotaSource);
            //插入指标值表 （根据公式计算指标值）
            QuotaValue quotaValue1 = new QuotaValue();
            for (Integer qId : quotaIds) {
                Float sumValue = 0f;
                //在指标值表查询此指标id指标sum值
                QueryWrapper queryWrapper = new QueryWrapper();
                queryWrapper.eq("QUOTA_ID", qId);
                List<QuotaValue> quotaValueList = quotaValueMapper.selectList(queryWrapper);
                for (QuotaValue quotaValue : quotaValueList) {
                    String dimStr = quotaValue.getDimensions();
                    List<String> strList1 = Arrays.asList(dimStr.split(",")).stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
                    List<Integer> strList = strList1.stream().map((m) -> Integer.valueOf(m)).collect(Collectors.toList());
                    if (strList.containsAll(dimIdList)) {//判断该维度列表是否包含共有维度列表
                        sumValue += quotaValue.getSm();//这里是getsm还是getvalue？ -------------待处理
                    }
                }
                quotaIdValueMap.put(qId, sumValue);
            }

            for (QuotaFormula quotaFormula : quotaFormulaList) {
                if (quotaFormula.getFormulaType().equals("0")) {//预指标
                    //预指标id转成指标值表中的sum值
                    formulaList.add(quotaIdValueMap.get(quotaFormula.getFormulaTextId()));
                } else if (quotaFormula.getFormulaType().equals("1")) {//计算符
                    //计算符id转为计算符名称
                    formulaList.add(quotaFormulaOperatorMapper.selectById(quotaFormula.getFormulaTextId()).getOperator());
                }
            }
            String formulaStr = "";
            for (Object str : formulaList) {
                formulaStr += str;
            }
            SimpleFormulaAnalysis formula = new SimpleFormulaAnalysis(formulaStr);
            quotaValue1.setQuotaId(quota.getId());
            quotaValue1.setDimensions(dimIds.substring(0, dimIds.length() - 1));
            quotaValue1.setValue((float) formula.getResult());
            quotaValue1.setCode(quota.getCode());
            quotaValue1.setUpdateDate(new Date());
            quotaValueMapper.insert(quotaValue1);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }

    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean createQuotaByQuotaFromType(QuotaCreateDto quotaCreateDto) {
        String dimIds = "";
        Integer quotaId = null;
        List<Integer> quotaIds = new ArrayList<>();//存储计算公式中的预指标id集合
        List<Integer> dimIdList = new ArrayList<>();//存储共有具体维度id集合
        List<Object> formulaList = new ArrayList<>();//顺序存储计算公式各项内容（预指标id，计算符）
        Map<Integer, Float> quotaIdValueMap = new HashMap<>();//存储预指标id对应的共有维度的指标值

        try {
            Map<Integer, Integer> dimMap = quotaCreateDto.getDimIntMap();//具体维度id对应一级维度id 的map集合

            //插入指标表
            Quota quota = new Quota();
            quota.setStatus("1");
            BeanUtils.copyProperties(quotaCreateDto, quota);
            quota.setUpdateDate(new Date());
            quotaMapper.insert(quota);
            quotaIds = quotaCreateDto.getQuotaFormulaList().stream()
                    .filter(quotaFormula -> DefineConstant.FormulaTypeEnum.IS_QUOTA.getCode().equals(quotaFormula.getFormulaType()))
                    .map(QuotaFormula::getFormulaTextId).collect(Collectors.toList());
            //插入指标来源表
            QuotaSource quotaSource = new QuotaSource();
            quotaSource.setQuotaId(quota.getId());
            quotaSource.setFormula(quotaCreateDto.getFormula());
            quotaSource.setUpdateDate(new Date());

            for (Map.Entry<Integer, Integer> entry : dimMap.entrySet()) {
                dimIds += entry.getKey() + ",";
                //插入指标与维度关系表（一级维度）
                QuotaDimensionRelation quotaDimensionRelation = new QuotaDimensionRelation();
                quotaDimensionRelation.setQuotaId(quota.getId());
                quotaDimensionRelation.setDimensionId(entry.getValue());
                quotaDimensionRelation.setUpdateDate(new Date());

                quotaDimensionRelationMapper.insert(quotaDimensionRelation);

                //插入指标与维度关系表（具体维度）
                QuotaDimRelationDetail quotaDimRelationDetail = new QuotaDimRelationDetail();
                quotaDimRelationDetail.setQuotaId(quota.getId());
                quotaDimRelationDetail.setDimensionId(entry.getKey());
                quotaDimRelationDetail.setRootDimId(entry.getValue());
                quotaDimRelationDetail.setUpdateDate(new Date());

                quotaDimRelationDetailMapper.insert(quotaDimRelationDetail);
                dimIdList.add(entry.getKey());
            }
            quotaSource.setDimensions(dimIds.substring(0, dimIds.length() - 1));
            quotaSourceMapper.insert(quotaSource);
            //插入指标值表 （根据公式计算指标值）
            QuotaValue quotaValue1 = new QuotaValue();
            for (Integer qId : quotaIds) {
                Float sumValue = 0f;
                Float value1 = 0f;//用于计算最大/最小值
                Integer count = 0;//用于计算计数/平均值
                //在指标值表查询此指标id指标列表
                QueryWrapper queryWrapper = new QueryWrapper();
                queryWrapper.eq("QUOTA_ID", qId);
                List<QuotaValue> quotaValueList = quotaValueMapper.selectList(queryWrapper);
                if (quotaValueList.size() == 0) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return false;
                }
                for (QuotaValue quotaValue : quotaValueList) {
                    String dimStr = quotaValue.getDimensions();
                    List<String> strList1 = Arrays.asList(dimStr.split(",")).stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
                    List<Integer> strList = strList1.stream().map((m) -> Integer.valueOf(m)).collect(Collectors.toList());
                    if (strList.containsAll(dimIdList)) {//判断该维度列表是否包含共有维度列表
                        if (quotaCreateDto.getTypeId().equals("0")) {//根据指标值生成
                            if (quotaValue.getSm() != null) {
                                sumValue += quotaValue.getSm();
                            }
                        } else if (quotaCreateDto.getTypeId().equals("1")) {//根据最大值生成
                            if (quotaValue.getMx() != null) {
                                if (value1.compareTo(quotaValue.getMx()) == 1) {

                                } else {
                                    value1 = quotaValue.getMx();
                                }
                            }
                        } else if (quotaCreateDto.getTypeId().equals("2")) {//根据最小值生成
                            if (quotaValue.getMn() != null) {
                                if (count == 0) {
                                    value1 = quotaValue.getMn();
                                    count++;
                                }
                                if (value1.compareTo(quotaValue.getMn()) == 1) {
                                    value1 = quotaValue.getMn();
                                }
                            }
                        } else if (quotaCreateDto.getTypeId().equals("3")) {//根据计数生成
                            count++;
                        } else if (quotaCreateDto.getTypeId().equals("4")) {//根据平均值生成
                            count++;
                            if (quotaValue.getSm() != null) {
                                value1 += quotaValue.getSm();
                            }
                        }
                    }
                }
                switch (quotaCreateDto.getTypeId()) {
                    case "0"://根据指标值生成
                        quotaIdValueMap.put(qId, sumValue);
                        break;
                    case "1"://根据最大值生成
                        quotaIdValueMap.put(qId, value1);
                        break;
                    case "2"://根据最小值生成
                        quotaIdValueMap.put(qId, value1);
                        break;
                    case "3"://根据计数生成
                        quotaIdValueMap.put(qId, (float) count);
                        break;
                    case "4"://根据平均值生成
                        quotaIdValueMap.put(qId, (float) SimpleFormulaAnalysis.divide2(value1, count));
                        break;
                    default:
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return false;
                }
            }

            //插入指标公式表
            List<QuotaFormula> quotaFormulaList = quotaCreateDto.getQuotaFormulaList();
            int i = 1;
            for (QuotaFormula quotaFormula : quotaFormulaList) {
                if (DefineConstant.FormulaTypeEnum.IS_QUOTA.getCode().equals(quotaFormula.getFormulaType())) {
                    Float quotaValueSum = quotaIdValueMap.get(quotaFormula.getFormulaTextId());
                    quotaFormula.setFormulaValue(quotaValueSum == null ? 0.0f : quotaValueSum);
                }
                quotaFormula.setQuotaId(quota.getId());
                quotaFormula.setOrderNum(i);
                this.baseMapper.insert(quotaFormula);//执行插入
                i++;
            }

            for (QuotaFormula quotaFormula : quotaFormulaList) {
                if (quotaFormula.getFormulaType().equals("0")) {//预指标
                    //预指标id转成指标值表中的sum值
                    formulaList.add(quotaIdValueMap.get(quotaFormula.getFormulaTextId()));
                } else if (quotaFormula.getFormulaType().equals("1")) {//计算符
                    //计算符id转为计算符名称
                    formulaList.add(quotaFormulaOperatorMapper.selectById(quotaFormula.getFormulaTextId()).getOperator());
                }
            }
            String formulaStr = "";
            for (Object str : formulaList) {
                formulaStr += str;
            }
            SimpleFormulaAnalysis formula = new SimpleFormulaAnalysis(formulaStr);
            quotaValue1.setQuotaId(quota.getId());
            quotaValue1.setDimensions(dimIds.substring(0, dimIds.length() - 1));
            quotaValue1.setValue((float) formula.getResult());
            quotaValue1.setCode(quota.getCode());
            quotaValue1.setUpdateDate(new Date());
            quotaValueMapper.insert(quotaValue1);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }
    }
}

